package cn.easy.mortgage.config;

import cn.easy.weixin.utils.CacheHolder;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * Created by cao on 16/7/21.
 */
@Component
public class WxMpFilter implements Filter {

    private final static Logger logger = LoggerFactory.getLogger(WxMpFilter.class);
    @Autowired
    private WxMpConfigStorage wxMpConfigStorage;
    @Autowired
    private WxMpService wxMpService;
    private WxMpMessageRouter wxMpMessageRouter;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        WxMpMessageHandler handler = new WxMpMessageHandler() {
            @Override
            public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map<String, Object> map,
                                            WxMpService wxMpService,
                                            WxSessionManager wxSessionManager) throws WxErrorException {
                WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content("测试加密消息").fromUser(wxMpXmlMessage.getToUser()).toUser(wxMpXmlMessage.getFromUser()).build();
                return m;
            }
        };

        WxMpMessageHandler eventHandler = new WxMpMessageHandler() {
            @Override
            public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map<String, Object> map,
                                            WxMpService wxMpService,
                                            WxSessionManager wxSessionManager) throws WxErrorException {

                if (CacheHolder.getCacheValue(wxMpXmlMessage.getEventKey()) == null) {
                    CacheHolder.putCacheValue(wxMpXmlMessage.getEventKey(), wxMpXmlMessage.getFromUser());
                }

                if (WxConsts.EventType.CLICK.equals(wxMpXmlMessage.getEvent())) {
                    if ("contact_us_cinda".equals(wxMpXmlMessage.getEventKey())) {
                        WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT()
                                .content("浙江信达新财富投资管理有限公司\n" +
                                        "地址：杭州市江干区城星路69号中天国开大厦8-11F\n" +
                                        "电话：400-8890-950\n" +
                                        "官网：www.cinda-newwealth.com\n" +
                                        "邮箱：Cinda—newwealth@upg.cn")
                                .fromUser(wxMpXmlMessage.getToUser())
                                .toUser(wxMpXmlMessage.getFromUser())
                                .build();
                        return m;
                    }
                }

                return null;
            }
        };

        wxMpMessageRouter = new WxMpMessageRouter(wxMpService);
        wxMpMessageRouter.rule().async(false).content("哈哈").handler(handler).end(); // 拦截内容为“哈哈”的消息
        wxMpMessageRouter.rule().async(false).event("SCAN").handler(eventHandler).end();

        logger.info("微信公众号服务启动成功~~~~~");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException,
                                                                                           ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        response.setContentType("text/html;charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK);

        String signature = request.getParameter("signature");
        String nonce = request.getParameter("nonce");
        String timestamp = request.getParameter("timestamp");

        if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
            // 消息签名不正确，说明不是公众平台发过来的消息
            response.getWriter().println("非法请求");
            return;
        }

        String echostr = request.getParameter("echostr");
        if (StringUtils.isNotBlank(echostr)) {
            // 说明是一个仅仅用来验证的请求，回显echostr
            response.getWriter().println(echostr);
            return;
        }

        String encryptType = StringUtils.isBlank(request.getParameter("encrypt_type")) ? "raw" : request.getParameter("encrypt_type");

        if ("raw".equals(encryptType)) {
            // 明文传输的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getInputStream());
            WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);
            if (outMessage != null) {
                response.getWriter().write(outMessage.toXml());
            }
            return;
        }

        if ("aes".equals(encryptType)) {
            // 是aes加密的消息
            String msgSignature = request.getParameter("msg_signature");
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(request.getInputStream(), wxMpConfigStorage,
                                                                       timestamp, nonce, msgSignature);
            WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);
            response.getWriter().write(outMessage.toEncryptedXml(wxMpConfigStorage));
            return;
        }

        response.getWriter().println("不可识别的加密类型");

        String a = wxMpConfigStorage.getAccessToken();
        System.out.println("=-========================" + a);
        return;
    }

    @Override
    public void destroy() {
        logger.warn("wx Mp filter destroy~~~~~~~~");
    }
}
